import pandas as pd
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
import streamlit as st
import os
from datetime import datetime, timedelta

from api_client import StockApiClient
from ai_client import AIAnalysisClient
from config import DEEPSEEK_API_KEY, ALIYUN_APPCODE

def format_number(num, precision=2):
    """格式化数字，添加千位分隔符"""
    if isinstance(num, (int, float)):
        return f"{num:,.{precision}f}"
    return num

def create_candlestick_chart(data, title="股票K线图"):
    """创建K线图"""
    fig = make_subplots(
        rows=2, 
        cols=1, 
        shared_xaxes=True,
        vertical_spacing=0.1,
        subplot_titles=(title, "成交量"),
        row_heights=[0.7, 0.3]
    )
    
    # 添加K线图
    fig.add_trace(
        go.Candlestick(
            x=data['日期'],
            open=data['开盘价'],
            high=data['最高价'],
            low=data['最低价'],
            close=data['收盘价'],
            name="K线"
        ),
        row=1, col=1
    )
    
    # 添加MA均线（如果数据中存在）
    ma_columns = [col for col in data.columns if col.startswith('MA') and not col.startswith('成交量MA')]
    ma_colors = ['blue', 'orange', 'purple', 'green', 'red', 'brown']
    
    for i, ma_col in enumerate(ma_columns):
        if ma_col in data.columns:
            fig.add_trace(
                go.Scatter(
                    x=data['日期'],
                    y=data[ma_col],
                    name=ma_col,
                    line=dict(color=ma_colors[i % len(ma_colors)], width=1)
                ),
                row=1, col=1
            )
    
    # 如果数据中没有MA均线，手动计算
    if not ma_columns and len(data) >= 5:
        data['MA5'] = data['收盘价'].rolling(window=5).mean()
        fig.add_trace(
            go.Scatter(
                x=data['日期'],
                y=data['MA5'],
                name="MA5",
                line=dict(color='blue', width=1)
            ),
            row=1, col=1
        )
    
    if not ma_columns and len(data) >= 20:
        data['MA20'] = data['收盘价'].rolling(window=20).mean()
        fig.add_trace(
            go.Scatter(
                x=data['日期'],
                y=data['MA20'],
                name="MA20",
                line=dict(color='orange', width=1)
            ),
            row=1, col=1
        )
    
    # 添加成交量柱状图
    colors = ['red' if row['涨跌幅'] >= 0 else 'green' for _, row in data.iterrows()] if '涨跌幅' in data.columns else ['blue'] * len(data)
    fig.add_trace(
        go.Bar(
            x=data['日期'],
            y=data['成交量'],
            name="成交量",
            marker_color=colors
        ),
        row=2, col=1
    )
    
    # 添加成交量MA（如果数据中存在）
    volume_ma_columns = [col for col in data.columns if col.startswith('成交量MA')]
    for i, vol_ma_col in enumerate(volume_ma_columns):
        if vol_ma_col in data.columns:
            fig.add_trace(
                go.Scatter(
                    x=data['日期'],
                    y=data[vol_ma_col],
                    name=vol_ma_col,
                    line=dict(color=ma_colors[i % len(ma_colors)], width=1)
                ),
                row=2, col=1
            )
    
    # 更新布局
    fig.update_layout(
        height=600,
        xaxis_rangeslider_visible=False,
        hovermode="x unified",
        legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="center", x=0.5)
    )
    
    return fig

def create_price_volume_chart(data):
    """创建价格与成交量关系图"""
    fig = px.scatter(
        data,
        x="日期",
        y="收盘价",
        size="成交量",
        color="涨跌幅",
        hover_name="日期",
        size_max=30,
        color_continuous_scale=["red", "lightgrey", "green"],
        range_color=[-5, 5],
        title="价格与成交量关系图"
    )
    
    fig.update_layout(height=400)
    return fig

def create_technical_indicators(data):
    """计算并创建技术指标图表"""
    # 计算MACD
    data['EMA12'] = data['收盘价'].ewm(span=12, adjust=False).mean()
    data['EMA26'] = data['收盘价'].ewm(span=26, adjust=False).mean()
    data['MACD'] = data['EMA12'] - data['EMA26']
    data['Signal'] = data['MACD'].ewm(span=9, adjust=False).mean()
    data['Histogram'] = data['MACD'] - data['Signal']
    
    # 计算RSI
    delta = data['收盘价'].diff()
    gain = delta.where(delta > 0, 0)
    loss = -delta.where(delta < 0, 0)
    avg_gain = gain.rolling(window=14).mean()
    avg_loss = loss.rolling(window=14).mean()
    rs = avg_gain / avg_loss
    data['RSI'] = 100 - (100 / (1 + rs))
    
    # 创建技术指标图表
    fig = make_subplots(
        rows=2, 
        cols=1, 
        shared_xaxes=True,
        vertical_spacing=0.1,
        subplot_titles=("MACD", "RSI"),
        row_heights=[0.5, 0.5]
    )
    
    # 添加MACD
    fig.add_trace(
        go.Scatter(
            x=data['日期'],
            y=data['MACD'],
            name="MACD",
            line=dict(color='blue', width=1)
        ),
        row=1, col=1
    )
    
    fig.add_trace(
        go.Scatter(
            x=data['日期'],
            y=data['Signal'],
            name="Signal",
            line=dict(color='red', width=1)
        ),
        row=1, col=1
    )
    
    # 添加MACD柱状图
    colors = ['red' if val >= 0 else 'green' for val in data['Histogram']]
    fig.add_trace(
        go.Bar(
            x=data['日期'],
            y=data['Histogram'],
            name="Histogram",
            marker_color=colors
        ),
        row=1, col=1
    )
    
    # 添加RSI
    fig.add_trace(
        go.Scatter(
            x=data['日期'],
            y=data['RSI'],
            name="RSI",
            line=dict(color='purple', width=1)
        ),
        row=2, col=1
    )
    
    # 添加RSI参考线
    fig.add_hline(y=70, line_dash="dash", line_color="red", row=2, col=1)
    fig.add_hline(y=30, line_dash="dash", line_color="green", row=2, col=1)
    
    # 更新布局
    fig.update_layout(
        height=500,
        hovermode="x unified",
        legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="center", x=0.5)
    )
    
    return fig

def display_stock_detail(api_client, ai_client, symbol, kline_type=240, kline_limit=90, ma_param=5):
    """显示股票详细信息
    
    Args:
        api_client: API客户端
        ai_client: AI分析客户端
        symbol: 股票代码
        kline_type: K线类型
        kline_limit: K线数量
        ma_param: MA均线参数
    """
    """显示股票详细信息"""
    try:
        # 获取股票报价
        with st.spinner("正在获取股票信息..."):
            # 获取股票报价
            quotes = api_client.get_stock_quotes([symbol])
            if quotes.empty:
                st.error("获取股票报价失败")
                return
            
            # 获取股票基本信息
            stock_code = symbol.replace("sh", "").replace("sz", "")
            if symbol.startswith("sh"):
                full_code = f"{stock_code}.SH"
            elif symbol.startswith("sz"):
                full_code = f"{stock_code}.SZ"
            elif symbol.startswith("bj"):
                full_code = f"{stock_code}.BJ"
            else:
                st.error(f"无法识别的股票代码格式: {symbol}")
                return
            
            info = api_client.get_stock_info(full_code)
            if not info:
                st.error("获取股票基本信息失败")
                return
            
            # 获取资金流向
            fund_flow = api_client.get_stock_fund_flow(stock_code)
            
            # 获取K线数据
            print(f"获取K线数据: 股票={symbol}, 类型={kline_type}, 数量={kline_limit}, MA={ma_param}")
            daily_kline = api_client.get_kline_data(symbol, kline_type=kline_type, limit=kline_limit, ma=ma_param)
            if daily_kline.empty:
                st.error("获取股票K线数据失败")
                return
            
            # 整合基本面信息
            basic_info = {
                "股票代码": symbol,
                "股票名称": quotes.iloc[0]["name"] if not quotes.empty else "",
                "最新价": float(quotes.iloc[0]["price"]) if not quotes.empty else 0,
                "涨跌幅": float(quotes.iloc[0]["changeRate"]) if not quotes.empty else 0,
                "市盈率(TTM)": float(info.get("pe", 0)),
                "市净率": float(info.get("pb_rate", 0)),
                "总市值(亿)": float(info.get("market_value", 0)) / 100000000,
                "流通市值(亿)": float(info.get("circulation_value", 0)) / 100000000 if "circulation_value" in info else float(info.get("market_value", 0)) / 100000000 * 0.7,
                "总股本(亿)": float(info.get("total_shares", 0)) / 100000000 if "total_shares" in info else 0,
                "流通股本(亿)": float(info.get("circulation_shares", 0)) / 100000000 if "circulation_shares" in info else 0,
                "股息率(%)": float(info.get("dv_ratio", 0)) if "dv_ratio" in info else 0,
                "行业": info.get("industry", ""),
                "振幅(%)": float(info.get("amplitude", 0)),
                "换手率(%)": float(quotes.iloc[0]["turnover"]) if not quotes.empty and "turnover" in quotes.columns else 0,
                "主力资金净流入(万)": fund_flow.get("main_net_inflow", 0) if fund_flow else 0,
                "超大单净流入(万)": fund_flow.get("super_large_net_inflow", 0) if fund_flow else 0,
                "大单净流入(万)": fund_flow.get("big_net_inflow", 0) if fund_flow else 0,
                "中单净流入(万)": fund_flow.get("mid_net_inflow", 0) if fund_flow else 0,
                "小单净流入(万)": fund_flow.get("small_net_inflow", 0) if fund_flow else 0,
                "52周最高": float(info.get("high52w", 0)) if "high52w" in info else float(info.get("high", 0)),
                "52周最低": float(info.get("low52w", 0)) if "low52w" in info else float(info.get("low", 0))
            }
            
            # 处理K线数据
            trading_data = daily_kline
            
            # 添加缺失的列
            if '涨跌幅' not in trading_data.columns and '开盘价' in trading_data.columns and '收盘价' in trading_data.columns:
                trading_data['涨跌幅'] = 0.0
                mask = trading_data['开盘价'] > 0
                trading_data.loc[mask, '涨跌幅'] = (trading_data.loc[mask, '收盘价'] - trading_data.loc[mask, '开盘价']) / trading_data.loc[mask, '开盘价'] * 100
            
            # 显示基本信息
            st.subheader(f"{basic_info['股票名称']} ({basic_info['股票代码']})")
            
            # 创建基本信息卡片
            col1, col2, col3 = st.columns(3)
            
            with col1:
                st.metric(
                    label="最新价", 
                    value=f"¥{basic_info['最新价']:.2f}", 
                    delta=f"{basic_info['涨跌幅']:.2f}%"
                )
                
                st.metric(
                    label="市盈率(TTM)", 
                    value=f"{basic_info['市盈率(TTM)']:.2f}"
                )
                
                st.metric(
                    label="总市值", 
                    value=f"{basic_info['总市值(亿)']:.2f}亿"
                )
            
            with col2:
                st.metric(
                    label="行业", 
                    value=f"{basic_info['行业']}"
                )
                
                st.metric(
                    label="市净率", 
                    value=f"{basic_info['市净率']:.2f}"
                )
                
                st.metric(
                    label="流通市值", 
                    value=f"{basic_info['流通市值(亿)']:.2f}亿"
                )
            
            with col3:
                st.metric(
                    label="股息率", 
                    value=f"{basic_info['股息率(%)']}%"
                )
                
                # 显示52周区间，如果数据存在
                if '52周最低' in basic_info and '52周最高' in basic_info:
                    st.metric(
                        label="52周区间", 
                        value=f"¥{basic_info['52周最低']:.2f} - ¥{basic_info['52周最高']:.2f}"
                    )
                    
                    # 计算52周位置百分比
                    if basic_info['52周最高'] > basic_info['52周最低']:
                        position = (basic_info['最新价'] - basic_info['52周最低']) / (basic_info['52周最高'] - basic_info['52周最低']) * 100
                        st.metric(
                            label="52周位置", 
                            value=f"{position:.2f}%"
                        )
            
            # 显示资金流向
            st.subheader("资金流向")
            
            fund_flow_cols = st.columns(5)
            
            with fund_flow_cols[0]:
                st.metric(
                    label="主力净流入", 
                    value=f"{basic_info['主力资金净流入(万)']:.2f}万",
                    delta=f"{basic_info['主力资金净流入(万)']:.2f}万",
                    delta_color="normal"
                )
            
            with fund_flow_cols[1]:
                st.metric(
                    label="超大单净流入", 
                    value=f"{basic_info['超大单净流入(万)']:.2f}万",
                    delta=f"{basic_info['超大单净流入(万)']:.2f}万",
                    delta_color="normal"
                )
            
            with fund_flow_cols[2]:
                st.metric(
                    label="大单净流入", 
                    value=f"{basic_info['大单净流入(万)']:.2f}万",
                    delta=f"{basic_info['大单净流入(万)']:.2f}万",
                    delta_color="normal"
                )
            
            with fund_flow_cols[3]:
                st.metric(
                    label="中单净流入", 
                    value=f"{basic_info['中单净流入(万)']:.2f}万",
                    delta=f"{basic_info['中单净流入(万)']:.2f}万",
                    delta_color="normal"
                )
            
            with fund_flow_cols[4]:
                st.metric(
                    label="小单净流入", 
                    value=f"{basic_info['小单净流入(万)']:.2f}万",
                    delta=f"{basic_info['小单净流入(万)']:.2f}万",
                    delta_color="normal"
                )
            
            # 创建K线图
            st.subheader("K线图")
            candlestick_fig = create_candlestick_chart(
                trading_data, 
                title=f"{basic_info['股票名称']} ({basic_info['股票代码']}) K线图"
            )
            st.plotly_chart(candlestick_fig, use_container_width=True)
            
            # 创建价格与成交量关系图
            price_volume_fig = create_price_volume_chart(trading_data)
            st.plotly_chart(price_volume_fig, use_container_width=True)
            
            # 创建技术指标图表
            st.subheader("技术指标")
            tech_fig = create_technical_indicators(trading_data)
            st.plotly_chart(tech_fig, use_container_width=True)
            
            # AI分析
            st.subheader("AI智能分析")
            
            analysis_tabs = st.tabs(["综合分析", "技术分析", "基本面分析", "投资建议"])
            
            with analysis_tabs[0]:
                with st.spinner("AI正在进行综合分析..."):
                    try:
                        comprehensive_analysis = ai_client.analyze_stock(
                            basic_info['股票代码'],
                            basic_info['股票名称'],
                            basic_info,
                            trading_data,
                            analysis_type="comprehensive"
                        )
                        st.markdown(comprehensive_analysis)
                    except Exception as e:
                        st.error(f"AI分析出错: {str(e)}")
            
            with analysis_tabs[1]:
                with st.spinner("AI正在进行技术分析..."):
                    try:
                        technical_analysis = ai_client.analyze_stock(
                            basic_info['股票代码'],
                            basic_info['股票名称'],
                            basic_info,
                            trading_data,
                            analysis_type="technical"
                        )
                        st.markdown(technical_analysis)
                    except Exception as e:
                        st.error(f"AI分析出错: {str(e)}")
            
            with analysis_tabs[2]:
                with st.spinner("AI正在进行基本面分析..."):
                    try:
                        fundamental_analysis = ai_client.analyze_stock(
                            basic_info['股票代码'],
                            basic_info['股票名称'],
                            basic_info,
                            trading_data,
                            analysis_type="fundamental"
                        )
                        st.markdown(fundamental_analysis)
                    except Exception as e:
                        st.error(f"AI分析出错: {str(e)}")
            
            with analysis_tabs[3]:
                with st.spinner("AI正在生成投资建议..."):
                    try:
                        investment_advice = ai_client.analyze_stock(
                            basic_info['股票代码'],
                            basic_info['股票名称'],
                            basic_info,
                            trading_data,
                            analysis_type="investment"
                        )
                        st.markdown(investment_advice)
                    except Exception as e:
                        st.error(f"AI分析出错: {str(e)}")
    
    except Exception as e:
        st.error(f"显示股票详细信息时出错: {str(e)}")

def stock_detail_app():
    """个股分析应用"""
    st.header("个股深度分析")
    
    # 获取API客户端
    api_client = StockApiClient(app_code=ALIYUN_APPCODE)
    
    # 获取DeepSeek API密钥
    api_key = os.environ.get("DEEPSEEK_API_KEY") or DEEPSEEK_API_KEY
    
    # 检查是否需要用户输入API密钥
    if api_key == "your_deepseek_api_key_here":
        api_key = st.text_input("请输入DeepSeek API密钥", type="password", 
                              help="您可以在config.py文件中设置默认的API密钥，避免每次输入")
        if not api_key:
            st.warning("请提供DeepSeek API密钥以启用AI分析功能")
            return
    
    # 创建两列布局，左侧为参数设置，右侧为内容区域
    col_params, col_content = st.columns([1, 3])
    
    with col_params:
    
        # 添加K线周期选择
        st.header("参数设置")
        kline_type = st.selectbox(
            "K线周期",
            [
                ("1分钟", 1),
                ("5分钟", 5),
                ("15分钟", 15),
                ("30分钟", 30),
                ("60分钟", 60),
                ("120分钟", 120),
                ("日K", 240),
                ("周K", 1200),
                ("月K", 7200),
                ("年K", 86400)
            ],
            index=6,  # 默认选择日K
            format_func=lambda x: x[0]
        )
        
        kline_limit = st.slider(
            "K线数量", 
            min_value=10, 
            max_value=200, 
            value=90,
            step=10
        )
        
        ma_values = st.multiselect(
            "MA均线",
            [5, 10, 15, 20, 25, 30],
            default=[5, 10]
        )
        ma_param = ','.join(map(str, ma_values)) if ma_values else None
        
        # 股票代码输入
        symbol = st.text_input("请输入股票代码（如：sh600000或sz000001）")
        
        # 分析按钮
        analyze_button = st.button("分析", use_container_width=True)
        
        if not symbol and analyze_button:
            st.info("请输入股票代码")
    
    with col_content:
        try:
            # 初始化AI客户端
            ai_client = AIAnalysisClient(api_key=api_key)
            
            # 首次加载页面时显示的内容
            if not analyze_button or not symbol:
                st.markdown("""
                ### 个股深度分析功能
                
                输入股票代码，获取股票的详细信息、K线图、技术指标和AI智能分析。
                
                #### 功能特点
                
                - **基本面数据**：市盈率、市净率、股息率等关键指标
                - **技术分析**：K线图、移动平均线、MACD、RSI等技术指标
                - **资金流向**：主力资金、大单、中单、小单净流入情况
                - **AI智能分析**：由DeepSeek AI提供的综合分析、技术分析、基本面分析和投资建议
                
                #### 使用方法
                
                1. 在左侧输入股票代码（以sh或sz开头，如sh600000、sz000001）
                2. 选择K线周期和其他参数
                3. 点击"分析"按钮
                4. 查看分析结果和AI建议
                
                > 注意：AI分析结果仅供参考，不构成投资建议。投资有风险，决策需谨慎。
                """)
            # 当用户点击分析按钮时
            elif analyze_button and symbol:
                # 获取选择的K线类型和参数
                selected_kline_type = kline_type[1]  # 获取选择的K线类型值
                selected_limit = kline_limit
                selected_ma = ma_param
                print(f"开始分析股票: {symbol}, K线类型: {selected_kline_type}, 数量: {selected_limit}, MA: {selected_ma}")
                display_stock_detail(api_client, ai_client, symbol, 
                                    kline_type=selected_kline_type, 
                                    kline_limit=selected_limit, 
                                    ma_param=selected_ma)
        except Exception as e:
            st.error(f"初始化AI客户端时出错: {str(e)}")
